home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / Pascal / Applications / NIH Image 1.59 / Macros / Plotting Macros < prev    next >
Encoding:
Text File  |  1995-10-25  |  19.4 KB  |  661 lines  |  [TEXT/Imag]

  1. macro 'Plot Histogram';
  2. var
  3.   max,scale:real;
  4.   i,margin,width,height:integer;
  5. begin
  6.   SaveState;
  7.   Margin:=10;
  8.   width:=256;
  9.   height:=0.6*256;
  10.   Measure;
  11.   SetForegroundColor(255);
  12.   SetBackgroundColor(0);
  13.   SetLineWidth(1);
  14.   SetNewSize(width+2*margin,height+2*margin);
  15.   MakeNewWindow('Histogram');
  16.   MakeRoi(margin,margin-1,width,height+1);
  17.   DrawBoundary;
  18.   max:=0;
  19.   for i:=1 to 254 do
  20.   if histogram[i]> max then max:=histogram[i];
  21.   scale:=height/max;
  22.   for i:=1 to 254 do begin
  23.     MakeRoi(margin+i,margin,1,histogram[i]*scale);
  24.     SetForegroundColor(i);
  25.     fill;
  26.  end;
  27.   SelectAll;
  28.   FlipVertical;
  29.   KillRoi;
  30.   RestoreState;
  31. end;
  32.  
  33. macro 'Stack Histogram';
  34. var
  35.   max,scale:real;
  36.   i,margin,width,height:integer;
  37. begin
  38.   SaveState;
  39.   Margin:=10;
  40.   width:=256;
  41.   height:=0.6*256;
  42.   Measure;
  43.   SetForegroundColor(255);
  44.   SetBackgroundColor(0);
  45.   SetLineWidth(1);
  46.   SetNewSize(width+2*margin,height+2*margin);
  47.   MakeNewWindow('Histogram');
  48.   MakeRoi(margin,margin-1,width,height+1);
  49.   DrawBoundary;
  50.   max:=0;
  51.   for i:=1 to 254 do
  52.   if histogram[i]> max then max:=histogram[i];
  53.   scale:=height/max;
  54.   for i:=1 to 254 do begin
  55.     MakeRoi(margin+i,margin,1,histogram[i]*scale);
  56.     SetForegroundColor(i);
  57.     fill;
  58.  end;
  59.   SelectAll;
  60.   FlipVertical;
  61.   KillRoi;
  62.   RestoreState;
  63. end;
  64.  
  65. procedure DoColumnPlot(MaxCount: integer);
  66. {Plots the User1 column in the Results table.}
  67. var
  68.    xmin,xmax,ymin,ymax,i,xscale,yscale:real;
  69.    width,height,margin,pwidth,pheight:integer;
  70.    y,pbottom, barWidth, barLeft, barTop:integer;
  71.    sum:integer;
  72. begin
  73.   SaveState;
  74.   margin:=40;
  75.   width:=500;
  76.   height:=300;
  77.   sum:=0;
  78.   ymin:=0;
  79.   ymax:=-999999;
  80.   for i:=1 to maxCount do
  81.       if rUser1[i]>ymax then ymax:=rUser1[i];
  82.   xmin:=1;
  83.   xmax:=maxCount;
  84.   SetNewSize(width,height);
  85.   SetForeground(255);
  86.   SetBackground(0);
  87.   MakeNewWindow('Histogram');
  88.   pwidth:=width-2*margin;
  89.   pheight:=height-2*margin;
  90.   pbottom:=margin+pheight;
  91.   xscale:=pwidth/xmax;
  92.   yscale:=pheight/(ymax-ymin);
  93.   barWidth:=round(pwidth/maxCount)+1;
  94.   SetForeground(255);
  95.   SetBackground(0); 
  96.   SetLineWidth(1);
  97.   for i:=0 to maxCount-1 do begin
  98.      barLeft:=margin+i*xscale;
  99.      barTop:=pbottom-(rUser1[i+1]-ymin)*yscale;
  100.      MakeRoi(barLeft, barTop, barWidth, pBottom-barTop);
  101.      fill;
  102.      sum:=sum+(i+1)*rUser1[i+1];
  103.   end;
  104.   KillRoi;
  105.   MoveTo(margin,margin);
  106.   LineTo(margin,margin+pheight);
  107.   SetFont('Geneva');
  108.   SetFontSize(9);
  109.   SetText('Centered');
  110.   MoveTo(margin+4,margin+pheight+12);
  111.   writeln(xmin:1:2);
  112.   MoveTo(margin+pwidth,margin+pheight+12);
  113.   writeln(xmax:1:2);
  114.   SetText('Right Justified');
  115.   MoveTo(margin-2,margin+pheight-5);
  116.   writeln(ymin:1:2);
  117.   MoveTo(margin-2,margin);
  118.   writeln(ymax:1:2);
  119.   MoveTo(margin+pwidth/2-15, margin+pheight+12);
  120.   RestoreState;
  121.   ShowMessage('sum=',sum:1,'\ymax=',ymax:1);
  122. end;
  123.  
  124.  
  125. macro 'Plot Histogram Using Bins';
  126. var
  127.   i, nBins, bin: integer;
  128.   ValuesPerBin, TotalArea: real;
  129.    n, lower, upper, nValues: integer;
  130.    first, last: integer;
  131. begin
  132.   ResetCounter;
  133.   nBins:=GetNumber('Number of Bins (1-256)', 10);
  134.   SetUser1Label('%');
  135.   SetUser2Label('Area');
  136.   Measure;
  137.   TotalArea := rArea[rCount];
  138.   GetThreshold(lower, upper);
  139.   if (lower = 0) and (upper = 0) then
  140.      upper := 255;
  141.   nValues := upper - lower + 1;
  142.   n := 0;
  143.   for i := lower to upper do
  144.      n := n + histogram[i];
  145.   ValuesPerBin := nValues / nBins;
  146.   for bin := 1 to nBins do
  147.       rUser1[bin] := 0;
  148.   {for i := lower to upper do begin
  149.       bin := trunc((i - lower) / ValuesPerBin) + 1;
  150.       rUser1[bin] := rUser1[bin] + Histogram[i];
  151.   end;}
  152.   SaveState;
  153.   SetFont('Monaco');
  154.   SetFontSize(9);
  155.   NewTextWindow('Histogram Data', 280, 450);
  156.   writeln(' Bin    Range   Count   Percent   Area');
  157.   for bin := 1 to nBins do begin
  158.       first := lower + trunc((nValues * (bin - 1)) / nBins);
  159.       last := lower + trunc((nValues * bin) / nBins) -1 ;
  160.       for i := first to last do
  161.          rUser1[bin] := rUser1[bin] + Histogram[i];
  162.       writeln(bin:3, first:6, last:4, rUser1[bin]:8, (rUser1[bin] / n) * 100:8:2, TotalArea * rUser1[bin] / n:10:2);
  163.   end;
  164.   RestoreState;
  165.   for bin := 1 to nBins do
  166.       rUser1[bin] :=  (rUser1[bin] / n) * 100.0;
  167.   for bin := 1 to nBins do
  168.       rUser2[bin] :=  TotalArea * rUser1[bin] / 100;
  169.   SetCounter(nBins);
  170.   DoColumnPlot(nBins);
  171. end;
  172.  
  173.  
  174. procedure DrawPerimeter;
  175. var
  176.   length1, length2: integer;
  177.   dx1, dx2, dy1, dy2: integer;
  178.   dxp1, dxp2, dyp1, dyp2: integer;
  179.   sumdx, sumdy, corners: integer;
  180.   corner: boolean;
  181.   perimeter: real;
  182. begin
  183.   RedLUT[254] := 255;
  184.   GreenLUT[254] := 0;
  185.   BlueLUT[254] := 0;
  186.   SetForeground(254);
  187.   sumdx := 0.0;
  188.   sumdy := 0.0;
  189.   corners := 0;
  190.   dx1 := xCoordinates[1] - xCoordinates[nCoordinates];
  191.   dy1 := yCoordinates[1] - yCoordinates[nCoordinates];
  192.   length1 := abs(dx1) + abs(dy1);
  193.   dxp1 := dx1;
  194.   if dxp1 > 1 then dxp1 := 1;
  195.   if dxp1 < -1 then dxp1 := -1;
  196.   dyp1 := dy1;
  197.   if dyp1 > 1 then dyp1 := 1;
  198.   if dyp1 < -1 then dyp1 := -1;
  199.   corner := false;
  200.   for i := 1 to nCoordinates do begin
  201.      dx2 := xCoordinates[i+1] - xCoordinates[i];
  202.      dy2 := yCoordinates[i+1] - yCoordinates[i];
  203. {showmessage(i, abs(dx1), abs(dy1)); wait(2);}
  204.      sumdx := sumdx + abs(dx1);
  205.      sumdy := sumdy + abs(dy1);
  206.      length2 := abs(dx2) + abs(dy2);
  207.      dxp2 := dx2;
  208.      if dxp2 > 1 then dxp2 := 1;
  209.      if dxp2 < -1 then dxp2 := -1;
  210.      dyp2 := dy2;
  211.      if dyp2 > 1 then dyp2 := 1;
  212.      if dyp2 < -1 then dyp2 := -1;
  213.      if (length1 > 1) or (not corner) then begin
  214.         MoveTo((xCoordinates[i]-dxp1)*scale+10, (yCoordinates[i]-dyp1)*scale+10);
  215.         LineTo((xCoordinates[i]+dxp2)*scale+10, (yCoordinates[i]+dyp2)*scale+10);
  216.         corner := true;
  217.         corners := corners + 1;
  218.      end else
  219.         corner := false;
  220.      dx1 := dx2;
  221.      dy1 := dy2;
  222.      dxp1 := dxp2;
  223.      dyp1 := dyp2;
  224.      length1 := length2;
  225.   end;
  226.   perimeter := sumdx + sumdy;
  227. end;
  228.  
  229. procedure ShowPerimeter;
  230. var
  231.   length1, length2: integer;
  232.   dx1, dx2, dy1, dy2: integer;
  233.   sumdx, sumdy, nCorners: integer;
  234.   corner: boolean;
  235.   perimeter: real;
  236. begin
  237.   sumdx := 0.0;
  238.   sumdy := 0.0;
  239.   nCorners := 0;
  240.   dx1 := xCoordinates[1] - xCoordinates[nCoordinates];
  241.   dy1 := yCoordinates[1] - yCoordinates[nCoordinates];
  242.   length1 := abs(dx1) + abs(dy1);
  243.   corner := false;
  244.   for i := 1 to nCoordinates do begin
  245.      dx2 := xCoordinates[i+1] - xCoordinates[i];
  246.      dy2 := yCoordinates[i+1] - yCoordinates[i];
  247.      sumdx := sumdx + abs(dx1);
  248.      sumdy := sumdy + abs(dy1);
  249.      length2 := abs(dx2) + abs(dy2);
  250.      if (length1 > 1) or (not corner) then begin
  251.         corner := true;
  252.         nCorners := nCorners + 1;
  253.      end else
  254.         corner := false;
  255.      dx1 := dx2;
  256.      dy1 := dy2;
  257.      length1 := length2;
  258.   end;
  259.   perimeter := sumdx + sumdy;
  260.   MoveTo(width/3,height/3 + 40);
  261.   Writeln('perimeter1=', perimeter:1:2);
  262.   Writeln('perimeter2=', perimeter - nCorners * (2 - sqrt(2)):1:2);
  263.   Writeln('perimeter3=', perimeter*0.948 - nCorners * (2 - 1.34):1:2);
  264. end;
  265.  
  266. procedure DrawX(x, y:integer);
  267. begin
  268.   moveto(x+3, y+3);
  269.   lineto(x-3, y-3);
  270.   moveto(x+3, y-3);
  271.   lineto(x-3, y+3);
  272.   lineto(x, y);
  273. end;
  274.  
  275.  
  276. macro 'Plot XY Coordinates [X]';
  277. {Plots the X-Y Coordinates of the current ROI.}
  278. var
  279.   i,w,h,width,height:integer;
  280.   xbase,ybase,RoiWidth,RoiHeight:integer
  281.   x,y,scale,xmax,ymax:real 
  282. begin
  283.   RequiresVersion(1.48);
  284.   if nCoordinates=0 then begin
  285.     beep;
  286.     PutMessage('No X-Y Coordinates available.');
  287.     exit;
  288.   end;
  289.   GetRoi(xbase,ybase,RoiWidth,RoiHeight);
  290.   SaveState;
  291.   InvertY(false);
  292.   xmax:=0;
  293.   ymax:=0;
  294.   for i:=1 to nCoordinates do begin
  295.     x:=xCoordinates[i];
  296.     y:=yCoordinates[i];
  297.     if x>xmax then xmax:=x;
  298.     if y>ymax then ymax:=y;
  299.   end;
  300.   scale:=sqrt((300*300)/(xmax*ymax));
  301.   if (xmax*scale)>500 then scale:=500/xmax;
  302.   if (ymax*scale)>500 then scale:=500/ymax;
  303.   SetForegroundColor(255);
  304.   SetBackgroundColor(0);
  305.   SetNewSize(xmax*scale+20,ymax*scale+20);
  306.   MakeNewWindow('Outline');
  307.   MoveTo(xCoordinates[1]*scale+10,yCoordinates[1]*scale+10);
  308.   for i:=2 to nCoordinates do begin
  309.     LineTo(xCoordinates[i]*scale+10,yCoordinates[i]*scale+10);
  310.     if nCoordinates < 100 then
  311.        DrawX(xCoordinates[i]*scale+10,yCoordinates[i]*scale+10);
  312.   end;
  313.   SetFont('Helvetica');
  314.   SetFontSize(12);
  315.   SetText('No background, Left Justified');
  316.   GetPicSize(width,height);
  317.   MoveTo(width/3,height/3);
  318.   Writeln(nCoordinates:1,' coordinate pairs');
  319.   Writeln('Origin=',xbase:1,', ',ybase:1);
  320.   Writeln('xmax=',xmax:1, ', ymax=',ymax:1,);
  321.   {DrawPerimeter;}
  322.   {ShowPerimeter;}
  323.   RestoreState;
  324. end;
  325.  
  326.  
  327. procedure PlotProfile2(integrate:boolean);
  328. var
  329.   xmin,xmax,ymin,ymax,i,xscale,yscale:real;
  330.   width,height,margin,pwidth,pheight:integer;
  331.   count:integer;
  332.   ppv:integer; {Pixels per Value}
  333. begin
  334.   SaveState;
  335.   margin:=40;
  336.   width:=500;
  337.   height:=300;
  338.   GetPlotData(count,ppv,ymin,ymax);
  339.   if count=0 then begin
  340.     PutMessage('No plot data available.');
  341.     exit;
  342.   end;
  343.   if integrate then begin
  344.      ymin:=ymin*ppv;
  345.      ymax:=ymax*ppv;
  346.   end;
  347.   xmin:=0;
  348.   xmax:=count-1;
  349.   SetNewSize(width,height);
  350.   SetForeground(255);
  351.   SetBackground(0);
  352.   MakeNewWindow('Plot');
  353.   pwidth:=width-2*margin;
  354.   pheight:=height-2*margin;
  355.   xscale:=pwidth/(xmax-xmin);
  356.   yscale:=pheight/(ymax-ymin);
  357.   SetForeground(255);
  358.   SetBackground(0); 
  359.   SetLineWidth(1); 
  360.   MoveTo(margin,margin);
  361.   if integrate then for i:=0 to count-1 do
  362.        LineTo(margin+i*xscale,margin+(PlotData[i]*ppv-ymin)*yscale)
  363.   else  for i:=0 to count-1 do
  364.         LineTo(margin+i*xscale,margin+(PlotData[i]-ymin)*yscale);
  365.   MakeRoi(margin,margin,pwidth+1,pheight+2);
  366.   MoveTo(margin,margin);
  367.   LineTo(margin+pwidth,margin);
  368.   MoveTo(margin,margin);
  369.   LineTo(margin,margin+pheight);
  370.   FlipVertical;
  371.   KillRoi;
  372.   SetFont('Geneva');
  373.   SetFontSize(9);
  374.   SetText('Centered');
  375.   MoveTo(margin+4,margin+pheight+12);
  376.   writeln(xmin:1:2);
  377.   MoveTo(margin+pwidth,margin+pheight+12);
  378.   writeln(xmax:1:2);
  379.   SetText('Right Justified');
  380.   MoveTo(margin-2,margin+pheight-5);
  381.   writeln(ymin:1:2);
  382.   MoveTo(margin-2,margin);
  383.   writeln(ymax:1:2);
  384.   RestoreState;
  385. end;
  386.  
  387.  
  388. macro 'Plot Profile';
  389. begin
  390.   PlotProfile2(false);
  391. end;
  392.  
  393. macro 'Plot Integrated Profile';
  394. begin
  395.   PlotProfile2(true);
  396. end;
  397.  
  398. macro 'Plot Radial Profiles… [R]';
  399. var
  400.   x1,y1,x2,y2,pi,angle,delta:real;
  401.   LineWidth,i,nLines,radius,PlotWidth,PlotHeight:integer;
  402.   MinPlotWidth,hMargin,vMargin,PlotLeft,PlotTop:integer;
  403.   LeftMargin,RightMargin,TopMargin,BottomMargin:integer;
  404.   ImageWindow,PlotWindow:integer;
  405.   nPixels,mean,mode,min,max:real;
  406. begin
  407.   RequiresVersion(1.54);
  408.   SaveState;
  409.   GetLine(x1,y1,x2,y2,LineWidth);
  410.   if x1<0 then begin
  411.     PutMessage('Please select a point by clicking with the line tool.');
  412.     exit;
  413.   end;
  414.   radius:=GetNumber('Radius:',20);
  415.   nLines:=GetNumber('Number of Lines:',8);
  416.   MinPlotWidth:=140;
  417.   pi:=3.14159;
  418.   delta:=2.0*pi/nLines;
  419.   angle:=0.0;
  420.   PlotWidth:=radius;
  421.   if PlotWidth<MinPlotWidth then PlotWidth:=MinPlotWidth;
  422.   PlotHeight:=0.4*PlotWidth;
  423.   SetPlotSize(PlotWidth,PlotHeight);
  424.   MakeOvalRoi(x1-radius,y1-radius,radius*2,radius*2);
  425.   Measure;
  426.   GetResults(nPixels,mean,mode,min,max);
  427.   min:=min-10;
  428.   if min<0 then min:=0;
  429.   max:=max+10;
  430.   if max>255 then max:=255;
  431.   SetPlotScale(cValue(min),cValue(max));
  432.   SetPlotLabels(false);
  433.   hMargin:=5;
  434.   vMargin:=5;
  435.   LeftMargin:=38;
  436.   TopMargin:=10;
  437.   RightMargin:=20;
  438.   BottomMargin:=20;
  439.   PlotLeft:=hMargin-LeftMargin;
  440.   PlotTop:=vMargin-TopMargin;
  441.   SetNewSize(PlotWidth+2*hMargin,PlotHeight*nLines);
  442.   SetForegroundColor(255);
  443.   SetBackgroundColor(0);
  444.   ImageWindow:=PicNumber;
  445.   MakeNewWindow('Plots');
  446.   PlotWindow:=PicNumber;
  447.   SelectPic(ImageWindow);
  448.   for i:=1 TO nLines do begin
  449.     x2:=x1+round(radius*cos(angle));
  450.     y2:=y1+round(radius*sin(angle));
  451.     MakeLineRoi(x1,y1,x2,y2);
  452.     PlotProfile;
  453.     Copy;
  454.     SelectPic(PlotWindow);
  455.     MakeRoi(PlotLeft,PlotTop,PlotWidth+LeftMargin+RightMargin,
  456.           PlotHeight+TopMargin+BottomMargin);
  457.     Paste;
  458.     DoOr;
  459.     PlotTop:=PlotTop+PlotHeight-1;
  460.     SelectPic(ImageWindow);
  461.     angle:=angle+delta;
  462.   end;
  463.   RestoreState;
  464. end;
  465.  
  466.  
  467. macro 'Radial Intensity Distibution…';
  468. var
  469.   x1,y1,x2,y2,pi,angle,delta:real;
  470.   radius,ymin,ymax,sum:real;
  471.   i,j,LineWidth,nLines,count,ppv:integer;
  472. begin
  473.   RequiresVersion(1.54);
  474.   SaveState;
  475.   GetLine(x1,y1,x2,y2,LineWidth);
  476.   if x1<0 then begin
  477.     PutMessage('Please select a point by clicking with the line tool.');
  478.     exit;
  479.   end;
  480.   radius:=GetNumber('Radius (pixels):',50);
  481.   nLines:=GetNumber('Number of Lines:',25);
  482.   for i:= 1 to radius do rUser1[i]:=0;
  483.   pi:=3.14159;
  484.   delta:=2.0*pi/nLines;
  485.   angle:=0.0;
  486.   for i:=1 to nLines do begin
  487.     x2:=x1+round(radius*cos(angle));
  488.     y2:=y1+round(radius*sin(angle));
  489.     MakeLineRoi(x1,y1,x2,y2);
  490.     GetPlotData(count,ppv,ymin,ymax);
  491.     for j:=1 to count do
  492.         rUser1[j]:=rUser1[j]+PlotData[j];
  493.     angle:=angle+delta;
  494.   end;
  495.   RestoreState;
  496.   DoColumnPlot(radius);
  497. end;
  498.  
  499.  
  500. macro 'Circular Profile Plot [C]';
  501. var
  502.   radius,pi,angle,dx,dy,delta:real;
  503.   x1,y1,x2,y2:real;
  504.   npoints,i,value,LineWidth,x,y,px:integer;
  505. begin
  506.   GetLine(x1,y1,x2,y2,LineWidth);
  507.   if x1< 0 then begin
  508.     PutMessage('Please select a point by clicking with the line tool.');
  509.     exit;
  510.   end;
  511.   x:=x1+(x2-x1)/2;
  512.   y:=y1+(y2-y1)/2;
  513.   radius:=sqrt(sqr(x2-x1)+sqr(y2-y1))/2;
  514.   if radius<3 then begin
  515.     PutMessage('The line selection must be longer than 5 pixels.');
  516.     exit;
  517.   end;
  518.   npoints:=radius*2;
  519.   pi:=3.14159;
  520.   delta:=2.0*pi/npoints;
  521.   angle:=0.0;
  522.   px:=0;
  523.   for i:=1 TO npoints do begin
  524.     dx:=round(radius*cos(angle));
  525.     dy:=round(radius*sin(angle));
  526.     value:=GetPixel(x+dx,y+dy);
  527.     PutPixel(x+dx,y+dy,255);
  528.     PutPixel(px,0,value);
  529.     px:=px+1;
  530.     angle:=angle+delta;
  531.   end;
  532.   MakeLineRoi(0,0,npoints,0);
  533.   PlotProfile;
  534.   KillRoi;
  535. end;
  536.  
  537. macro 'Export Profile Plots…';
  538. var
  539.   y,yInc,width,height,n:integer;
  540. begin
  541.   yInc:=GetNumber('Y Increment:',10);
  542.   GetPicSize(width,height);
  543.   y:=0;
  544.   n:=0;
  545.   SetExport('Plot Values');
  546.   repeat
  547.     MakeLineRoi(0,y,width-1,y);
  548.     PlotProfile;
  549.     Export('PLOT',n:4);
  550.     n:=n+1;
  551.     y:=y+yInc;
  552.   until y>=height;
  553. end;
  554.  
  555.  
  556. procedure PlotMeans;
  557. {Plots the mean column in the Results table.}
  558. var
  559.    xmin,xmax,ymin,ymax,i,xscale,yscale:real;
  560.   width,height,margin,pwidth,pheight:integer;
  561.   y,pbottom:integer;
  562. begin
  563.   margin:=40;
  564.   width:=500;
  565.   height:=300;
  566.   ymax:=-999999;
  567.   ymin:=999999;
  568.   for i:=1 to rCount do begin
  569.     y:=rMean[i];
  570.     if y>ymax then ymax:=y;
  571.     if y<ymin then ymin:=y;
  572.   end;
  573.   xmin:=0;
  574.   xmax:=rCount-1;
  575.   SetNewSize(width,height);
  576.   SetForeground(255);
  577.   SetBackground(0);
  578.   MakeNewWindow('Z-Axis Profile Plot');
  579.   pwidth:=width-2*margin;
  580.   pheight:=height-2*margin;
  581.   pbottom:=margin+pheight;
  582.   xscale:=pwidth/(xmax-xmin);
  583.   yscale:=pheight/(ymax-ymin);
  584.   SetForeground(255);
  585.   SetBackground(0); 
  586.   SetLineWidth(1);
  587.   MoveTo(margin,pbottom-(rMean[1]-ymin)*yscale);
  588.   for i:=2 to rCount do
  589.      LineTo(margin+(i-1)*xscale,pbottom-(rMean[i]-ymin)*yscale);
  590.   MoveTo(margin,pbottom);
  591.   LineTo(margin+pwidth,pbottom);
  592.   MoveTo(margin,margin);
  593.   LineTo(margin,margin+pheight);
  594.   SetFont('Geneva');
  595.   SetFontSize(9);
  596.   SetText('Centered');
  597.   MoveTo(margin+4,margin+pheight+12);
  598.   writeln(xmin:1:2);
  599.   MoveTo(margin+pwidth,margin+pheight+12);
  600.   writeln(xmax:1:2);
  601.   SetText('Right Justified');
  602.   MoveTo(margin-2,margin+pheight-5);
  603.   writeln(ymin:1:2);
  604.   MoveTo(margin-2,margin);
  605.   writeln(ymax:1:2);
  606. end;
  607.  
  608. macro 'Plot Z-Axis Profile [Z]';
  609. {Plots the average density of an roi through a stack.}
  610. var
  611.   left,top,width,height,i:integer;
  612. begin
  613.   if (nPics=0) or (nSlices=0) then begin
  614.      PutMessage('This macro requires a stack.');
  615.      exit;
  616.   end;
  617.   GetRoi(left,top,width,height);
  618.   if width=0 then begin
  619.      PutMessage('Selection required.');
  620.      exit;
  621.   end;
  622.   ResetCounter;
  623.   {SetOptions('Mean');}
  624.   for i:= 1 to nSlices do begin
  625.      SelectSlice(i);
  626.      Measure;
  627.   end;
  628.   PlotMeans;
  629.  end;
  630.  
  631.  
  632. macro 'Plot XYZ';
  633. {
  634. Plots X-Y coordinate points with an optional intensity(Z). Values are read from
  635. a 2 or 3 column tab-delimited text file. Data must be scaled as follows:
  636. 0<=X<width; 0<=Y<height; 0<=Z<=255.
  637. }
  638. var
  639.   width,height:integer;
  640. begin
  641.   SaveState;
  642.   width:=500;
  643.   height:=500;
  644.   SetNewSize(width,height);
  645.   SetForeground(255);
  646.   SetBackground(0);
  647.   MakeNewWindow('Plot');
  648.   PlotXYZ;
  649.   RestoreState;
  650. end;
  651.  
  652. macro 'Draw Fitted Ellipse in White';
  653. var
  654.   left,top,width,height:real;
  655. begin
  656.   GetRoi(left,top,width,height);
  657.   if width=0 then begin
  658.     PutMessage('This macro requires a selection.');
  659.     exit;
  660.   end;
  661.